<?php
namespace jm\helper;

/**
* 文件相关（上传、下等）
*/
class File
{
    /**
     * 单个上传文件处理
     * @param  think\File  $file            上传的文件对象。
     * @param  string  $removeFileStr       要删除的文件的路径（表中记录的 /static/...）。
     * @param  string  $path                上传文件保存的绝对路径。
     * @param  boolean $keepName            上传后是否保留文件的名称。
     * @param  boolean $dateDirectory       是否生成当前日期的目录。
     * @param  string  $ext                 上传文件的扩展名判断。
     * @return array             ['errcode'=>0成功非0失败, 'message'=>'信息', 'url'=>'图片访问的url，成功时才有该key']
     */
    public static function save($file, $removeFileStr='', $path='', $keepName=false, $dateDirectory=true, $ext='jpg,jpeg,png,gif,pm4')
    {
        // 如果不保留上传文件的文件名称，则会以当前日期生成目录，保存的文件放在该目录下。
        // 有时候，不希望有日期目录，或者希望保留源文件名。
        
        /*
        pre($file);
        think\File Object
        (
            [error:think\File:private] => 
            [filename:protected] => C:\Windows\phpFA22.tmp
            [saveName:protected] => 
            [rule:protected] => date
            [validate:protected] => Array
                (
                )

            [isTest:protected] => 
            [info:protected] => Array
                (
                    [name] => hwzhongsong.png
                    [type] => image/png
                    [tmp_name] => C:\Windows\phpFA22.tmp
                    [error] => 0
                    [size] => 3911
                )

            [hash:protected] => Array
                (
                )

            [pathName:SplFileInfo:private] => C:\Windows\phpFA22.tmp
            [fileName:SplFileInfo:private] => phpFA22.tmp
            [openMode:SplFileObject:private] => r
            [delimiter:SplFileObject:private] => ,
            [enclosure:SplFileObject:private] => "
        )
         */

        // 自动创建需要的目录
        
        try {
            if (empty($path)) {
                $path = ROOT_PATH .'public/static/upload';
            }
            $url = '';

            // 希望保留原名
            if ($keepName) {
                // 希望生成日期目录
                if ($dateDirectory) {
                    $currTime = \jm\helper\DateTime::YMD();
                    $path .= '/'. $currTime;
                    if (!is_dir($path)) {
                        mkdir($path);
                    }
                }
                $info = $file->validate(['ext' => $ext])->move($path, '');
                if ($info) {
                    // 成功上传后 获取上传信息
                    // 输出 jpg
                    // echo $info->getExtension();
                    // 输出 20160820/42a79759f284b767dfcb2a0197904287.jpg
                    // echo $info->getSaveName();
                    // 输出 42a79759f284b767dfcb2a0197904287.jpg
                    // echo $info->getFilename(); 
                    $url = substr($path, strlen(ROOT_PATH .'public')) .'/'. $info->getSaveName();
                } else {
                    // 上传失败获取错误信息
                    // echo $file->getError();
                    return ['errcode'=>4003, 'message'=>$file->getError()];
                }
            } else {
                // 不保留原名
                
                // 生成日期目录，这是框架的默认行为；
                if ($dateDirectory) {
                    $info = $file->validate(['ext' => $ext])->move($path);
                    if ($info) {
                        // 成功上传后 获取上传信息
                        // 输出 jpg
                        // echo $info->getExtension();
                        // 输出 20160820/42a79759f284b767dfcb2a0197904287.jpg
                        // echo $info->getSaveName();
                        // 输出 42a79759f284b767dfcb2a0197904287.jpg
                        // echo $info->getFilename(); 
                        $url = substr($path, strlen(ROOT_PATH .'public')) . '/' . $info->getSaveName();
                    } else {
                        // 上传失败获取错误信息
                        // echo $file->getError();
                        return ['errcode'=>4004, 'message'=>$file->getError()];
                    }                    
                } else {
                    // 不生成日期目录，需要自己实现了。因为框架里没有这个做法。                    
                    $fileInfo = $file->getInfo();

                    // 扩展名验证
                    if (!empty($ext) && (strpos($ext, substr($file->getExtension(), 1)) === false)) {
                        return ['errcode'=>4001, 'message'=>'文件扩展名不合法'];
                    }

                    // 保存文件
                    $saveFileName = md5(microtime(true)) . strrchr($fileInfo['name'], '.');
                    if(is_uploaded_file($fileInfo['tmp_name']) && move_uploaded_file($fileInfo['tmp_name'], $path . '/' . $saveFileName))
                    {
                        $url = substr($path, strlen(ROOT_PATH .'public')) . '/' . $saveFileName;                        
                    }
                }
            }

            if (!empty($url)) {
                // 上传成功
                // 删除旧图片（删除失败也无所谓，不用报错）
                if ($removeFileStr !== '') {
                    try {
                        unlink(ROOT_PATH .'public'. $removeFileStr);
                    } catch(\Exception $e) {}
                }

                $url = str_replace('\\', '/', $url);

                return ['errcode'=>200, 'message'=>'文件上传成功', 'data'=>$url];
            }
            return ['errcode'=>4002, 'message'=>'文件上传失败'];
        } catch (\Exception $e) {
            return ['errcode'=>4000, 'message'=>'异常：'. $e->getMessage()];
        }
    }

    // 多个文件上传处理
    /*
    array(2) {
      [0]=>
      object(think\File)#27 (13) {
        ["error":"think\File":private]=>
        string(0) ""
        ["filename":protected]=>
        string(22) "C:\Windows\php8084.tmp"
        ["saveName":protected]=>
        NULL
        ["rule":protected]=>
        string(4) "date"
        ["validate":protected]=>
        array(0) {
        }
        ["isTest":protected]=>
        NULL
        ["info":protected]=>
        array(6) {
          ["key"]=>
          string(4) "file"
          ["name"]=>
          string(5) "0.jpg"
          ["type"]=>
          string(10) "image/jpeg"
          ["tmp_name"]=>
          string(22) "C:\Windows\php8084.tmp"
          ["error"]=>
          int(0)
          ["size"]=>
          int(1597)
        }
        ["hash":protected]=>
        array(0) {
        }
        ["pathName":"SplFileInfo":private]=>
        string(22) "C:\Windows\php8084.tmp"
        ["fileName":"SplFileInfo":private]=>
        string(11) "php8084.tmp"
        ["openMode":"SplFileObject":private]=>
        string(1) "r"
        ["delimiter":"SplFileObject":private]=>
        string(1) ","
        ["enclosure":"SplFileObject":private]=>
        string(1) """
      }
      [1]=>
      object(think\File)#28 (13) {
        ["error":"think\File":private]=>
        string(0) ""
        ["filename":protected]=>
        string(22) "C:\Windows\php8085.tmp"
        ["saveName":protected]=>
        NULL
        ["rule":protected]=>
        string(4) "date"
        ["validate":protected]=>
        array(0) {
        }
        ["isTest":protected]=>
        NULL
        ["info":protected]=>
        array(6) {
          ["key"]=>
          string(4) "file"
          ["name"]=>
          string(7) "222.jpg"
          ["type"]=>
          string(10) "image/jpeg"
          ["tmp_name"]=>
          string(22) "C:\Windows\php8085.tmp"
          ["error"]=>
          int(0)
          ["size"]=>
          int(5179)
        }
        ["hash":protected]=>
        array(0) {
        }
        ["pathName":"SplFileInfo":private]=>
        string(22) "C:\Windows\php8085.tmp"
        ["fileName":"SplFileInfo":private]=>
        string(11) "php8085.tmp"
        ["openMode":"SplFileObject":private]=>
        string(1) "r"
        ["delimiter":"SplFileObject":private]=>
        string(1) ","
        ["enclosure":"SplFileObject":private]=>
        string(1) """
      }
    }
     */
    public static function saveMulti($fileArr, $removeFileArr=[], $path='', $keepName=false, $dateDirectory=true, $ext='jpg,jpeg,png,gif,mp4') {
        try {            
            $fileLength = count($fileArr);
            $removeFileLength = count($removeFileArr);

            if ($removeFileLength < $fileLength) {
                for ($i = 0; $i < ($fileLength - $removeFileLength); $i++) {
                    array_push($removeFileArr, '');
                }
            }

            $retData = ['errcode'=>200, 'message'=>'文件上传成功', 'data'=>[]];
            foreach ($fileArr as $key => $file) {
                $temp = self::save($file, $removeFileArr[$key], $path, $keepName, $dateDirectory, $ext);
                if ($temp['errcode'] === 200) {
                    array_push($retData['data'], $temp['data']);
                } else {
                    return ['errcode'=>4001, $temp['message']];
                }
            }
            return $retData;
        } catch (\Exception $e) {
            return ['errcode'=>4000, 'message'=>'异常：'. $e->getMessage()];
        }
    }

    // 下载文件（$filename 文件的绝对路径）
    public static function download($filename) {
        //设置脚本的最大执行时间，设置为0则无时间限制
        set_time_limit(0);
        ini_set('max_execution_time', '0');

        // 通过header()发送头信息
        // 因为不知道文件是什么类型的，告诉浏览器输出的是字节流
        header('content-type:application/octet-stream');

        //告诉浏览器返回的文件大小类型是字节
        header('Accept-Ranges:bytes');
        //获得文件大小
        $filesize = filesize($filename);//(此方法无法获取到远程文件大小)

        //告诉浏览器返回的文件大小
        header('Accept-Length:'. $filesize);
        // header('Content-Length:'. $filesize);

        //告诉浏览器文件作为附件处理并且设定最终下载完成的文件名称
        header('content-disposition:attachment;filename='. basename($filename));

        //针对大文件，规定每次读取文件的字节数为1024字节，直接输出数据
        $read_buffer = 1024; 
        $handle = fopen($filename, 'rb');

        //只要没到文件尾，就一直读取 
        while(!feof($handle)) { 
            echo fread($handle, $read_buffer);
        }

        //关闭句柄
        fclose($handle);
        exit;
    }

    // 把请求的 base64 字符串存储文件；
    // $str = substr($content, 0, 50);
    // // logss('上传订单的图片内容：' . $str);
    // $commaPosition = strpos($str, ',');
    // $commaPosition++;
    // //$imageString = substr($base64String, $commaPosition);
    // $mime = substr($str, 5, (strpos($str, ';') - 5));
    // $imageType = substr($mime, 6);
    // $fileName = $code;
    // $path = 'userOrders/' . dt();
    // if (!is_dir($path)) {
    //     mkdir($path, 0777, true);
    // }
    // $filePath = $path . '/' . $fileName . '.' . $imageType;
    // file_put_contents($filePath, base64_decode(substr($content, $commaPosition)));
}